﻿/*
 *	Copyright (c) 2009 Queensland University of Technology. All rights reserved.
 *	The QUT Bioinformatics Collection is open source software released under the 
 *	Microsoft Public License (Ms-PL): http://www.microsoft.com/opensource/licenses.mspx.
 */
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace QUT.Bio.Map2D {

	/// <summary>
	/// A PositionInterpolator is used to animate a positioned element along a line 
	/// from (X0,Y0) to (X1,Y1).
	/// </summary>

	public class PositionInterpolator: DependencyObject {
	#pragma warning disable 1591
		private IPositioned element;
		private double x0;
		private double y0;
		private double x1;
		private double y1;

		public PositionInterpolator(
			IPositioned element,
			double x0,
			double y0,
			double x1,
			double y1
		) : this( element, x1, y1 ) {
			this.x0 = x0;
			this.y0 = y0;
			element.X = x0;
			element.Y = y0;
		}

		public PositionInterpolator(
			IPositioned element,
			double x1,
			double y1
		) {
			this.element = element;
			CopyElementPosition();
			this.x1 = x1;
			this.y1 = y1;
			T = 0;
		}

		public double X0 {
			get {
				return x0;
			}
			set {
				x0 = value;
			}
		}

		public double Y0 {
			get {
				return y0;
			}
			set {
				y0 = value;
			}
		}

		public double X1 {
			get {
				return x1;
			}
			set {
				x1 = value;
			}
		}

		public double Y1 {
			get {
				return y1;
			}
			set {
				y1 = value;
			}
		}
		
		private bool updateDisabled = false;
		
		private void DisableUpdate () {
			lock( this ) {
				updateDisabled = true;
			}
		}
		
		private void EnableUpdate () {
			lock ( this ) {
				updateDisabled = false;
			}
		}

		/// <summary>
		/// Resets (X0,Y0) to the current position of the positioned element, and
		/// sets T = 0.
		/// </summary>
		
		public void CopyElementPosition() {
			this.x0 = element.X;
			this.y0 = element.Y;
			DisableUpdate();
			T = 0;
			EnableUpdate();
		}

		public static DependencyProperty TProperty = DependencyProperty.Register(
			"T",
			typeof( double ),
			typeof( PositionInterpolator ),
			new PropertyMetadata( 0.0, TChanged )
		);

		public double T {
			get {
				return ( (double) ( base.GetValue( PositionInterpolator.TProperty ) ) );
			}
			set {
				base.SetValue( PositionInterpolator.TProperty, value );
			}
		}

		private static void TChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) {
			double newValue = (double) e.NewValue;
			double oldValue = (double) e.OldValue;

			if ( oldValue != newValue ) {
				PositionInterpolator p = (PositionInterpolator) d;
				
				if ( ! p.updateDisabled ) {
					double t = newValue;
					p.element.X = ( 1 - t ) * p.x0 + t * p.x1;
					p.element.Y = ( 1 - t ) * p.y0 + t * p.y1;
				}
			}
		}
	#pragma warning restore 1591
	}
}
